<template>
  <view class="component scroll-menu">
    <scroll-view scroll-y scroll-with-animation class="menu-tab-view menu-scroll-view" :scroll-top="scrollTop">
      <view v-for="(item, index) in tabbar" :key="index" class="menu-tab-item"
        :class="[current == index ? 'menu-tab-item-active' : '']" :data-current="index" @tap.stop="swichMenu(index)"
        :scroll-into-view="itemId">
        <view class="icon"></view>
        <view class="text">{{ item.name }}</view>
      </view>
    </scroll-view>
    <scroll-view scroll-y scroll-with-animation class="menu-panel-view" :scroll-top="scrollRightTop"
      @scroll="panelScroll">
      <view class="panel">
        <menuType2View :data="tabbar[current].list" v-if="type == 'type2'" />
        <template v-if="type == 'customItem'">
          <slot :data="tabbar[current].list"></slot>
        </template>
      </view>
    </scroll-view>
  </view>
</template>

<script name="ScrollMenu" setup>
import menuView from './modules/menu-view.vue';
import menuType2View from './modules/menu-type2-view.vue';
const props = defineProps({
  type: {
    type: String,
    default: 'type2'
  },
  data: {
    type: Array,
    default: () => {
      return [];
    }
  },
  modelValue: {
    type: Object,
    default: () => {
      return { index: 0 };
    }
  }
});
const instance = getCurrentInstance();
const menuHeight = ref(0);
const menuItemHeight = ref(0);
const arr = reactive([]); // 每个面板到顶部的距离的数组 [top]

const data = reactive({
  tabbar: props.data,
  oldScrollTop: 0,
  scrollTop: 0, //tab标题的滚动条位置
  scrollRightTop: 0, // 右边菜单栏的滚动条位置
  current: 0, //
  timer: null, // 定时器
});
const { tabbar, scrollTop, oldScrollTop, scrollRightTop, current, timer } = toRefs(data);


const emit = defineEmits(['selected', 'update:modelValue', 'switch-tab']);

const _value = computed({
  get() {
    return props.modelValue
  },
  set(val) {
    emit('update:modelValue', val)
  }
})



async function swichMenu(index) {
  if (index == current.value) return;

  // switchTab()
  // const currentVal = _value.value;
  // if (arr.length == 0) {
  //   await getMenuItemTop();
  // }
  // if (index == current.value) return;
  // // 面板滚动
  // scrollRightTop.value = oldScrollTop.value;
  // console.log('swichMenu', index);

  nextTick(() => {
    scrollRightTop.value = arr[index];
    current.value = index;
    leftMenuStatus(index);
    emit('switch-tab', index);
  });
}
const leftMenuStatus = async (index) => {
  current.value = index;
  // 如果为0，意味着尚未初始化
  if (menuHeight.value == 0 || menuItemHeight.value == 0) {
    menuHeight.value = await getElementHeight('.menu-scroll-view');
    menuItemHeight.value = await getElementHeight('.menu-tab-item');

    const mH = menuHeight.value;
    const mItemH = menuItemHeight.value;
    console.log('mH', mH, 'mItemH', mItemH);
    // 将菜单菜单活动item垂直居中
    scrollTop.value = index * mH + mItemH / 2 - mH / 2;
  }
}

// 右侧面板栏滚动方法
const panelScroll = async (e) => {
  oldScrollTop.value = e.detail.scrollTop;
  if (arr.length == 0) {
    await getMenuItemTop();
  }
  if (timer.value) return;
  if (!menuHeight.value) {
    await getElRect('menu-scroll-view', menuHeight);
  }

  setTimeout(() => { // 节流
    timer.value = null;
    // scrollHeight为右边菜单垂直中点位置
    let scrollHeight = e.detail.scrollTop + menuHeight / 2;
    for (let i = 0; i < arr.length; i++) {
      let height1 = arr[i];
      let height2 = arr[i + 1];
      // 如果不存在height2，意味着数据循环已经到了最后一个，设置左边菜单为最后一项即可
      if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
        leftMenuStatus(i);
        return;
      }
    }
  }, 10)
}

// 获取元素的高度值

/**
 * 获取元素的高度
 * @param {string} selector - 元素的选择器
 * @returns {Promise<number>} - 元素的高度
 */
async function getElementHeight(selector) {
  return new Promise((resolve, reject) => {
    if (!instance) {
      reject(new Error('无法获取当前组件实例'));
      return;
    }

    const query = uni.createSelectorQuery().in(instance.proxy);

    query.select(selector).boundingClientRect(data => {
      if (data) {

        resolve(data.height);
      } else {
        reject(new Error('未找到目标元素'));
      }
    }).exec();
  });
}

/**
 * 动态设置高度
 * @param elClass 父级元素的选择器
 * @param dataVal
 */
async function getElRect(elClass, ref) {
  new Promise((resolve, reject) => {
    const query = uni.createSelectorQuery().in(instance.proxy);
    query.select('.' + elClass).fields({
      size: true
    }, res => {
      // 如果节点尚未生成，res值为null，循环调用执行
      if (!res) {
        setTimeout(() => {
          getElRect(elClass);
        }, 10);
        return;
      }
      ref.value = res.height;
      resolve();
    }).exec();
  })
}

// 获取右边菜单每个item到顶部的距离
const getMenuItemTop = () => {
  new Promise(resolve => {
    let selectorQuery = uni.createSelectorQuery();
    selectorQuery.selectAll('.panel-item').boundingClientRect((rects) => {
      // 如果节点尚未生成，rects值为[](因为用selectAll，所以返回的是数组)，循环调用执行
      if (!rects.length) {
        setTimeout(() => {
          getMenuItemTop();
        }, 10);
        return;
      }

      console.log('getMenuItemTop 方法 rects', rects);

      rects.forEach((rect) => {
        // 这里减去rects[0].top，是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
        console.log('getMenuItemTop rect.top', rect.top);

        arr.push(rect.top - rects[0].top);
        resolve();
      })
    }).exec()
  })
};

const menuOperateFn = (type, data) => {
  emit('selected', type, data);
}
provide('menuOperate', menuOperateFn);

onMounted(() => {
  getMenuItemTop();
  // 初始化
  const index = props?.modelValue?.index;
  if (index) {
    current.value = index;
  }
});
</script>

<style lang="scss" scoped>
@import "@/static/scss/theme.scss";

$rounded-corner-width: 24rpx;

.scroll-menu {
  height: 100%;
  display: flex;
  // :v-deep {

  .menu-tab {
    &-view {
      width: 200rpx;
      height: 100%;
    }

    &-item {
      padding: 16rpx 28rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 30rpx;
      color: #444;
      font-weight: 400;

      &:first-child {
        &::before {
          visibility: hidden;
        }
      }

      &:last-child {
        &::after {
          visibility: hidden;
        }
      }

      .text {
        padding-left: 16px;
        font-size: 30rpx;
        line-height: 40rpx;
      }

      .icon {
        visibility: hidden;
        background-color: $primary-color;
        position: absolute;
        height: 12rpx;
        width: 12rpx;
        border-radius: 6rpx;
        left: 16rpx;
      }

      &-active {
        position: relative;
        color: $primary;
        font-size: 30rpx;
        font-weight: 600;
        background: #fff;

        .icon {
          visibility: visible;
        }

        &:after,
        &:before {
          content: "";
          position: absolute;
          right: 0;
          z-index: 99;
          width: $rounded-corner-width;
          height: $rounded-corner-width;
          background: url('/static/images/scroll-menu_rounded-corner.png') no-repeat;
        }

        &:before {

          top: -$rounded-corner-width;
        }

        &:after {
          bottom: -$rounded-corner-width;
        }
      }
    }
  }

  // }

  .menu-panel-view {
    background-color: #fff;
    border-radius: 12px 0px 0px 0px;
  }
}
</style>
